package cc.rengu.redp.hawk.algorithm;

import cc.rengu.redp.hawk.domain.TimestampData;
import cc.rengu.redp.hawk.service.IndexAlgorithm;
import cc.rengu.redp.hawk.utils.HawkUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 周期均值算法
 *
 * 计算指定周期内（此刻的过去一段时间内），指定指标的均值
 */
@Slf4j
public class AverageInPeriod implements IndexAlgorithm {

    private final static String TAG_INPUT_INDEX_NAME = "inputIndexName";
    private final static String TAG_PERIOD = "period";

    @Override
    public String paramsSample() {
        JSONObject jsonObject = new JSONObject();
        /**
         * 定义配置参数：参与计算的指标名
         */
        jsonObject.put(TAG_INPUT_INDEX_NAME, "?");
        /**
         * 定义配置参数：时间长度（秒）
         */
        jsonObject.put(TAG_PERIOD, "?");
        return jsonObject.toJSONString();
    }

    @Override
    public String algorithmChineseName() {
        return "周期均值";
    }

    @Override
    public Float run(JSONObject algParams, Map<String, List<TimestampData>> timelineData, JSONObject currData) {
        //校验参数
        String inputIndexName = algParams.getString(TAG_INPUT_INDEX_NAME);
        String periodStr = algParams.getString(TAG_PERIOD);
        if (StringUtils.isBlank(inputIndexName) || StringUtils.isBlank(periodStr)) {
            log.warn("invalid configuration. algParams:[{}]", algParams.toJSONString());
            return 0.0f;
        }
        Long period = Long.valueOf(periodStr);
        if (period == null || period <= 0) {
            log.warn("invalid period. period:[{}]", period);
            return 0.0f;
        }
        Float currIndex = HawkUtil.jsonObjectValueToFloat(currData.get(inputIndexName));
        if (currIndex == null) {
            log.warn("current index data is null. currData:[{}]", currData.toJSONString());
            return 0.0f;
        }

        //获得指标的历史数据
        List<TimestampData> timestampDataList = timelineData.get(inputIndexName);
        if (timestampDataList == null || timestampDataList.size() == 0) {
            return currIndex;
        }
        //历史数据中的时间区间右值
        TimestampData maxTimestampData = timestampDataList.get(timestampDataList.size() - 1);
        //计算时间区间左值
        Long minTimestamp = maxTimestampData.getTimestamp() - period * 1000;
        //过滤有效的区间数据
        List<TimestampData> validData = timestampDataList
                .stream()
                .filter(i -> i.getTimestamp() >= minTimestamp)
                .collect(Collectors.toList());
        //历史求和
        Float sumAll = validData.stream()
                .map(i -> i.getIndexData())
                .reduce(0.0f, Float::sum);
        //再加上当前值
        sumAll += currIndex;
        //均值
        return sumAll / validData.size();
    }
}
